#include "stdafx.h"
#include "vscriptrendertest.h"

#include <QtDeclarative/QDeclarativeComponent>
#include <QtTreePropertyBrowser>
#include <qtpropertybrowser.h>
#include <QtVariantProperty>

#include "../../scriptEngine/vblank.h"
#include "../../scriptEngine/vcontrol.h"
#include "../../scriptEngine/vstyle.h"
#include "../../scriptEngine/vdata.h"
#include "../../scriptEngine/vtextedit.h"
#include "../../scriptEngine/vimage.h"
#include "../../scriptEngine/vtable.h"

#include "../../scriptEngine/vscriptengine.h"

VSimpleHighLighter::VSimpleHighLighter(QTextEdit* log, QTextDocument* parent)
	: m_log(log)
	, QSyntaxHighlighter(parent)
{
}

void VSimpleHighLighter::highlightBlock(const QString& text)
{
	//m_log->append(text);
}

VScriptRenderTest::VScriptRenderTest(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
	, m_blank(0)
	, m_curStyle(0)
{
	/*qmlRegisterType<VAbstractData>();
	qmlRegisterType<VAbstractControl>();
	qmlRegisterType<VBlank>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_BLANK));
	qmlRegisterType<VStyle>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_STYLE));
	qmlRegisterType<VTime>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_TIME));
	qmlRegisterType<VDate>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_DATE));
	qmlRegisterType<VString>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_STRING));
	qmlRegisterType<VInteger>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_INTEGER));
	qmlRegisterType<VReal>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_REAL));
	qmlRegisterType<VImage>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_IMAGE));
	qmlRegisterType<VTextEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_TEXTEDIT));
	qmlRegisterType<VTable>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_TABLE));
	qmlRegisterType<VCell>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V,VBLANK_MIN_V, qPrintable(VCTRL_CELL));*/

	ui.setupUi(this);	
	QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

	setDockOptions( QMainWindow::ForceTabbedDocks | QMainWindow::VerticalTabs | QMainWindow::AnimatedDocks );

	m_mdiArea = new QMdiArea;
	m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	setCentralWidget(m_mdiArea);

	QTabWidget* tabWidget = new QTabWidget(this);
	m_mdiArea->addSubWindow(tabWidget);

	m_scriptEngine = new VScriptEngine(tabWidget);
	
	if (!m_scriptEngine->execute(""))
		qDebug() << m_scriptEngine->errors();
	else
		qDebug() << "Script execute OK";
		
	/*m_scriptEdit = new QTextEdit(tabWidget);
	tabWidget->insertTab(EScriptEdit, m_scriptEdit, tr("QML Script"));
	
	m_editor = new QTextEdit(tabWidget);
	tabWidget->insertTab(ETextEdit, m_editor, tr("Blank"));	

	QDockWidget* dockObjInsp = new QDockWidget(this);
	dockObjInsp->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
	addDockWidget(Qt::RightDockWidgetArea, dockObjInsp);

	m_objInsp = new QTreeWidget;
	dockObjInsp->setWidget(m_objInsp);

	QDockWidget* dockPropEditor = new QDockWidget(this);
	dockPropEditor->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
	addDockWidget(Qt::RightDockWidgetArea, dockPropEditor);

	variantManager = new QtVariantPropertyManager(this);
	QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(this);
	
	m_propEditor = new QtTreePropertyBrowser(dockPropEditor);
	dockPropEditor->setWidget(m_propEditor);

	m_propEditor->setFactoryForManager(variantManager, variantFactory);

	QDockWidget* m_dockUtil = new QDockWidget(this);
	m_dockUtil->setAllowedAreas(Qt::BottomDockWidgetArea);
	addDockWidget(Qt::BottomDockWidgetArea, m_dockUtil);

	QWidget* utilWidget = new QWidget(m_dockUtil);
	QGridLayout* utilLayout = new QGridLayout(utilWidget);	
	m_dockUtil->setWidget(utilWidget);
	m_log = new QTextEdit(utilWidget);
	m_btnUpdate = new QPushButton("Update", m_dockUtil);
	utilLayout->addWidget(m_log, 0, 0);
	utilLayout->addWidget(m_btnUpdate, 0, 1);*/

	tabWidget->showMaximized();

	showMaximized();

	/*updateEnv();
	fillObjectInspector();

	//m_parserNotify = new VParserStatusNotify;
	
	m_renderDlg = new QDialog(this);	
	m_renderDlg->show();
	QRect dlgGeom = m_renderDlg->geometry();
	dlgGeom.setWidth(dlgGeom.width()/2);
	m_renderDlg->setGeometry(dlgGeom);

	QRect mainGeom = geometry();
	mainGeom.setLeft(dlgGeom.right()+10);
	mainGeom.setWidth(dlgGeom.width());
	mainGeom.setBottom(dlgGeom.bottom());
	setGeometry(mainGeom);

	QGridLayout* dlgLayout = new QGridLayout(m_renderDlg);
	m_editor = new QTextEdit(m_renderDlg);
	m_hl = new VSimpleHighLighter(ui.textEditLog, m_editor->document());

	dlgLayout->addWidget(m_editor);

	ui.lineEditPath->setText("test.qml");

	connect(ui.pushButtonUpdate, SIGNAL(clicked()), this, SLOT(onUpdateRender()));
	connect(ui.lineEditPath, SIGNAL(returnPressed()), this, SLOT(onUpdateRender()));		
	connect(m_editor, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPosChanged()));	
	//connect(ui.pushButtonReplace, SIGNAL(clicked()), this, SLOT(replaceSelText()));
	connect(ui.textEditContent, SIGNAL(cursorPositionChanged()), this, SLOT(replaceSelText()));*/

	/*connect(m_editor, SIGNAL(cursorPositionChanged()), this, SLOT(replaceSelText()));
	connect(m_btnUpdate, SIGNAL(clicked()), this, SLOT(updateEnv()));
	connect(m_objInsp, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(objInspItemClicked(QTreeWidgetItem*, int)));
	connect(variantManager, SIGNAL(valueChanged(QtProperty *, const QVariant &)),
		this, SLOT(valueChanged(QtProperty *, const QVariant &)));

	connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateTabScript(int)));*/
}

VScriptRenderTest::~VScriptRenderTest()
{

}

void VScriptRenderTest::updateEnv()
{
	if (updateScript())
		updateRender();
}

bool VScriptRenderTest::updateScript()
{
	
	//connect(&m_engine, SIGNAL(warnings(const QList<QDeclarativeError> &)), this, SLOT(qmlParseError(const QList<QDeclarativeError> &)));

	m_component = new QDeclarativeComponent(&m_engine, "test.qml", this); 
	QObject *obj = m_component->create(); 
	if(m_component->isError())
	{ 
		QString errorStr; 
		QList<QDeclarativeError> errors = m_component->errors(); 
		foreach (QDeclarativeError error, errors)
		{ 
			//errorStr += (error.line() > 0 ? QString::number(error.line()) + ": ":"") + error.description() + '\n'; 
			m_log->append(error.toString());
		} 
		
		//m_log->append(errorStr);
	}

	if (m_blank)
	{
		delete m_blank;
		m_blank = 0;
	}

	qDebug() << "updateScript()" << obj;

	m_blank = qobject_cast<VBlank* >(obj);

	if (!m_blank)
	{
		return false;
	}

	m_log->append("Script load OK");
	return true;
}

void VScriptRenderTest::updateRender()
{
	m_editor->clear();
	QTextCursor cursor(m_editor->textCursor());

	QTextTableFormat tableFormat;
	tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_None);

	/*QVector<QTextLength> constraints;
	for (int i=0; i<m_blank->controls()->count(); i++)
		constraints << QTextLength(QTextLength::VariableLength, 0);
	tableFormat.setColumnWidthConstraints(constraints);	*/

	cursor.beginEditBlock();

	QTextFrame* topFrame = cursor.currentFrame();

	cursor.setPosition(topFrame->lastPosition());
	
	QTextTable *table = 0;

	for (int i=0; i<m_blank->controlCollection().count(); ++i)
	{
		if (i == 0 || m_blank->controlCollection().at(i)->newLine())
		{
			if (table)
			{
				table->removeColumns(table->columns()-1, 1);
				QTextTableFormat tblFormat = table->format();
				QVector<QTextLength> constraints;//(tblFormat.columnWidthConstraints());
				int constCount = table->columns();//table->format().columnWidthConstraints().count(); 
				/*for (int k=0; k<constCount; ++k)
				{
					//constraints.replace(k, QTextLength(QTextLength::PercentageLength, 100/constraints.count()));
					constraints << QTextLength(QTextLength::PercentageLength, 100/constCount);
				}*/

				if (constCount == 1)
					constraints << QTextLength(QTextLength::PercentageLength, 100);

				tblFormat.setColumnWidthConstraints(constraints);
				table->setFormat(tblFormat);
			}

			cursor.setPosition(topFrame->lastPosition());
			//cursor.insertBlock();
			table = cursor.insertTable(1, 1, tableFormat);
		}		

		QTextTableCell cell;
		QTextCursor cellCursor;
		QTextCharFormat charFormat;
		QTextTableCellFormat cellFormat;		

		cell = table->cellAt(0, table->columns()-1);

		QTextBlockFormat blockAlignment;
		
		switch (m_blank->controlCollection().at(i)->hAlign())
		{
		case VAbstractControl::AlignLeft:
			blockAlignment.setAlignment(Qt::AlignLeft);
			break;
		case VAbstractControl::AlignHCenter:
			blockAlignment.setAlignment(Qt::AlignHCenter);
			break;
		case VAbstractControl::AlignRight:
			blockAlignment.setAlignment(Qt::AlignRight);
			break;
		}

		cellCursor = cell.firstCursorPosition();
		cellCursor.setBlockFormat(blockAlignment);

		if (VTextEdit* edit = qobject_cast<VTextEdit*>(m_blank->controlCollection().at(i)))
		{
			charFormat.setFont(edit->style()->font());
			QBrush brTextColor(edit->style()->color());
			QBrush brBgColor(edit->style()->bgColor());
			charFormat.setForeground(brTextColor);
			charFormat.setBackground(brBgColor);					
			//cellCursor = cell.firstCursorPosition();			
			cellCursor.insertText(edit->text(), charFormat);
		}
		else if (VImage* image = qobject_cast<VImage*>(m_blank->controlCollection().at(i)))
		{
			cellCursor.insertImage(image->image());
		}
		else if (VTable* t = qobject_cast<VTable*>(m_blank->controlCollection().at(i)))
		{
			//cellCursor = cell.firstCursorPosition();
			QTextTable* vTable = cellCursor.insertTable(t->cells().count(&t->cells())/t->header().count(&t->header()), t->header().count(&t->header()));

			qDebug() << "begin table" << t->name(); 
			for (int ii=0; ii<t->cells().count(&t->cells()); ++ii)
			{										
				int colIndex = ii%t->header().count(&t->header());
				QTextTableCell vCell = vTable->cellAt((ii-colIndex)/t->header().count(&t->header()), colIndex);
				QTextCursor vCursor = vCell.firstCursorPosition();

				VCell* c = t->cells().at(&t->cells(), ii);
				vCursor.insertText(c->value().toString());

				VAbstractData* data = t->header().at(&t->header(), ii%t->header().count(&t->header()));				
				if (VString* var = qobject_cast<VString*>(data))
					qDebug() << c->value().toString();
				else if (VInteger* var = qobject_cast<VInteger*>(data))
					qDebug() << c->value().toInt();
				else if (VReal* var = qobject_cast<VReal*>(data))
					qDebug() << c->value().toReal();
				else if (VDate* var = qobject_cast<VDate*>(data))
					qDebug() << c->value().toDate().toString("dd/MM/yy");
				else if (VTime* var = qobject_cast<VTime*>(data))
					qDebug() << c->value().toTime().toString();						
			}
			//qDebug() << "end table" << t->name() << "\n" ;			
		}
		table->insertColumns(table->columns(), 1);
	}
	table->removeColumns(table->columns()-1, 1);	
	/*QTextTableFormat tblFormat = table->format();
	QVector<QTextLength> constraints;//(tblFormat.columnWidthConstraints());
	int constCount = table->columns();//table->format().columnWidthConstraints().count(); 
	for (int k=0; k<constCount; ++k)
	{
		//constraints.replace(k, QTextLength(QTextLength::PercentageLength, 100/constraints.count()));
		constraints << QTextLength(QTextLength::PercentageLength, 100/constCount);
	}

	tblFormat.setColumnWidthConstraints(constraints);
	//tblFormat.setBorderStyle(QTextFrameFormat::BorderStyle_None);
	table->setFormat(tblFormat);*/
	cursor.endEditBlock();
}

void VScriptRenderTest::onCursorPosChanged()
{
	/*QTextFrame* currentFrame = cursor.currentFrame();
	for (QTextFrame::iterator frameIt = currentFrame->begin(); frameIt!=currentFrame->end(); ++frameIt)
	{
		ui.textEditLog->append(frameIt.currentBlock().text());
	}*/
	/*QTextTable* curTable = cursor.currentTable();
	if (curTable)
		//for (int i=0; i<curTable->columns(); ++i)
			ui.textEditLog->append(QString("%1").arg(curTable->cellAt(0, i).column()));*/

	//disconnect(m_editor, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPosChanged()));

	/*QTextDocument* doc = m_editor->document();
	QTextCursor tc = m_editor->textCursor();
	QTextBlock block = doc->findBlock(tc.position());
	/*tc.clearSelection();
	//tc.select(QTextCursor::LineUnderCursor);
	tc.select(QTextCursor::BlockUnderCursor);
	/*int firstRow = 0;
	int numRows = 1;
	int firstColumn = 0;
	int numColumns = 1;
	tc.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns);* /

	//ui.textEditLog->append(QString("%1").arg(cursor.position()));
	QTextCharFormat cf = block.charFormat();
	QBrush brBgColor(QColor(200, 200, 200));
	cf.setBackground(brBgColor);

	QList<QTextEdit::ExtraSelection> listSel;
	QTextEdit::ExtraSelection sel;
	sel.cursor = tc;
	sel.format = cf;
	listSel << sel;

	m_editor->setExtraSelections(listSel);* /
	//m_editor->textCursor().insertText("qwerty");
	
	//block.

	ui.textEditContent->clear();
	ui.textEditContent->append(block.text());*/
}

void VScriptRenderTest::replaceSelText()
{
	QTextCursor tc = m_editor->textCursor();
	QTextBlock block = m_editor->document()->findBlock(tc.position());
	tc.clearSelection();
	//tc.select(QTextCursor::BlockUnderCursor);
	//ui.textEditLog->append(QString("%1(%2) - %3").arg(block.position()).arg(block.length()).arg(tc.position()));
	tc.setPosition(block.position(), QTextCursor::MoveAnchor);
	tc.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, block.length()-1);
	//ui.textEditLog->append(tc.selectedText());

	QTextCharFormat cf = block.charFormat();
	QBrush brBgColor(QColor(200, 200, 200));
	cf.setBackground(brBgColor);

	QList<QTextEdit::ExtraSelection> listSel;
	QTextEdit::ExtraSelection sel;
	sel.cursor = tc;
	sel.format = cf;
	listSel << sel;

	m_editor->setExtraSelections(listSel);

	//tc.removeSelectedText();
	//tc.beginEditBlock();
	//if (tc.hasSelection())
	{
		//disconnect(ui.textEditContent, SIGNAL(cursorPositionChanged()), this, SLOT(replaceSelText()));
		//tc.insertText(ui.textEditContent->toPlainText());
	}

	//connect(m_editor, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPosChanged()));
	//tc.endEditBlock();

}

void VScriptRenderTest::fillObjectInspector()
{
	if (!m_blank)
	{
		m_log->append("Script not ready");
		return;
	}

	//
	/*QTreeWidgetItem* item = new QTreeWidgetItem;
	item->setText(0, "VBlank");
	item->setText(1, "Blank");
	m_objInsp->addTopLevelItem(item);

	//
	item->setText(0, "Styles");
	item->setText(1, "All styles");
	m_objInsp->*/

	QTreeWidgetItem* itemStyles = new QTreeWidgetItem;
	itemStyles->setText(0, "Styles");
	for (int i=0; i<m_blank->styleCollection().count(); ++i)
	{
		QTreeWidgetItem* item = new QTreeWidgetItem;
		item->setText(0, m_blank->styleCollection().at(i)->name());
		item->setText(1, m_blank->styleCollection().at(i)->metaObject()->className());
		itemStyles->addChild(item);
	}

	QTreeWidgetItem* itemControls = new QTreeWidgetItem;
	itemControls->setText(0, "Controls");
	for (int i=0; i<m_blank->controlCollection().count(); ++i)
	{
		QTreeWidgetItem* item = new QTreeWidgetItem;
		item->setText(0, m_blank->controlCollection().at(i)->name());
		item->setText(1, m_blank->controlCollection().at(i)->metaObject()->className());
		itemControls->addChild(item);
	}

	QTreeWidgetItem* itemRoot = new QTreeWidgetItem;
	itemRoot->setText(0, "VBlank");
	itemRoot->setText(1, m_blank->metaObject()->className());
	itemRoot->addChild(itemStyles);
	itemRoot->addChild(itemControls);
	
	QStringList labels;
	labels << tr("Object") << tr("Class");
	m_objInsp->setHeaderLabels(labels);
	m_objInsp->header()->setResizeMode(0, QHeaderView::Stretch);
	m_objInsp->header()->setResizeMode(1, QHeaderView::Stretch);

	m_objInsp->addTopLevelItem(itemRoot);
	m_objInsp->expandAll();
}

void VScriptRenderTest::updateExpandState()
{
	QList<QtBrowserItem *> list = m_propEditor->topLevelItems();
	QListIterator<QtBrowserItem *> it(list);
	while (it.hasNext())
	{
		QtBrowserItem *item = it.next();
		QtProperty *prop = item->property();
		idToExpanded[propertyToId[prop]] = m_propEditor->isExpanded(item);
	}
}

void VScriptRenderTest::addProperty(QtVariantProperty *property, const QString &id)
{
	propertyToId[property] = id;
	idToProperty[id] = property;
	QtBrowserItem *item = m_propEditor->addProperty(property);
	if (idToExpanded.contains(id))
		m_propEditor->setExpanded(item, idToExpanded[id]);
}

void VScriptRenderTest::clickStyleItem(VStyle* style)
{
	updateExpandState();

	m_curStyle = style;

	QMap<QtProperty*, QString>::ConstIterator itProp = propertyToId.constBegin();
	while (itProp != propertyToId.constEnd())
	{
		delete itProp.key();
		itProp++;
	}
	propertyToId.clear();
	idToProperty.clear();

	QtVariantProperty *property;

	property = variantManager->addProperty(QVariant::Color, tr("Color"));
	property->setValue(style->color());
	addProperty(property, QLatin1String("color"));

	property = variantManager->addProperty(QVariant::Color, tr("Background color"));
	property->setValue(style->bgColor());
	addProperty(property, QLatin1String("bgColor"));

	property = variantManager->addProperty(QVariant::Font, tr("Font"));
	property->setValue(style->font());
	addProperty(property, QLatin1String("font"));
}

void VScriptRenderTest::objInspItemClicked(QTreeWidgetItem* item, int column)
{
	QString name(item->text(0));
	VStyle* style = m_blank->findStyleByName(name);
	
	if (style)
		clickStyleItem(style);
}

void VScriptRenderTest::valueChanged(QtProperty *property, const QVariant &value)
{
	if (!propertyToId.contains(property))
		return;

	if (!m_curStyle)
		return;

	QString id = propertyToId[property];
	if (id == QLatin1String("color"))
	{
		m_curStyle->setColor(value.value<QColor>());
	} 
	else if (id == QLatin1String("bgColor"))
	{
		m_curStyle->setBgColor(value.value<QColor>());
	}
	else if (id == QLatin1String("font"))
	{
		m_curStyle->setFont(value.value<QFont>());
	}	

	updateRender();
}

void VScriptRenderTest::updateTabScript(int index)
{
	switch(index)
	{
	case EScriptEdit:
		Q_ASSERT(m_blank);
		m_scriptEdit->clear();
		m_scriptEdit->append(m_blank->serialize());
		break;
	case ETextEdit:
		if (!m_scriptEdit->toPlainText().isEmpty())
		{
			m_component->setData(m_scriptEdit->toPlainText().toUtf8(), QUrl());
			QObject *obj = m_component->create();
			
			if (m_blank)
			{
				delete m_blank;
				m_blank = 0;
			}

			qDebug() << "updateScript()" << obj;

			m_blank = qobject_cast<VBlank* >(obj);

			updateRender();
		}
		
		break;
	}
}

void VScriptRenderTest::qmlParseError(const QList<QDeclarativeError>& warnings)
{
	QDeclarativeError w;
	foreach(w, warnings)
		m_log->append(w.toString());
}